<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<style>
    #draggable {
        width: 200px;
        height: 20px;
        text-align: center;
        background: lightcoral;
    }

    .dropzone {
        width: 200px;
        height: 20px;
        background: aqua;
        margin-bottom: 10px;
        padding: 10px;
    }
</style>

<body>
<div id="wrapper">
    <div class="dropzone">
        <div id="draggable" draggable="true">
            a draggable div
        </div>
    </div>
    <div class="dropzone"></div>
    <div class="dropzone"></div>
    <div class="dropzone"></div>
</div>
<script>
    var dragged;
    const wDom = document.getElementById('wrapper')

    // 开始拖拽，也可用drag，不过drag，dragover在拖起的时候会持续触发， dragstart只触发一次
    wDom.addEventListener('dragstart', (e) => {
        dragged = e.target
        e.target.style.opacity = 0.5
        event.dataTransfer.setData('text/plain', JSON.stringify({}))
    })
    // 拖拽悬浮
    wDom.addEventListener('dragover', (e) => {
        e.preventDefault()
    })
    // 拖拽结束，还原源节点的透明度
    wDom.addEventListener('dragend', (e) => {
        e.target.style.opacity = ""
    })

    // 进入目标节点，高亮目标节点
    wDom.addEventListener('dragenter', (e) => {
        if (e.target.className === 'dropzone') {
            e.target.style.background = "red"
        }
    })
    // 离开源节点
    wDom.addEventListener('dragleave', (e) => {
        if (e.target.className === 'dropzone') {
            e.target.style.background = ""
        }
    })
    // 放进目标节点，取消目标节点的高亮，转移dom
    wDom.addEventListener('drop', (e) => {
        if (e.target.className === 'dropzone') {
            const data = event.dataTransfer.getData('text/plain')
            e.target.style.background = ""
            dragged.parentNode.removeChild(dragged)
            e.target.appendChild(dragged)
        }
    })
</script>
</body>

</html>
